﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using SHomeWorkshop.LunarConcept.Tools;

namespace SHomeWorkshop.LunarConcept.Commands.TextCommands
{
    /// <summary>
    /// 创建时间：2012年2月5日
    /// 创建者；  杨震宇
    /// 
    /// 主要用途：⑴读取自定义命令列表，生成用户自定义命令列表与内部命令列表的映射表（多对一）；
    ///           ⑵解析自定义命令，转换成内部命令文本；
    ///           ⑶根据内部命令，调用相关方法，执行相应操作。
    ///           
    /// 自定义命令类的条件：⑴类名必须以“_TC”开头，否则会无法调用。
    ///                       类名即内置命令文本，用户输入的命令文本将被转换（通过映射表）成内置命令，
    ///                       根据内置命令字符串（即类名），找到类，并调用必须实现的下列方法：
    ///                     ⑵类必须实现带一个string型参数的 static string Execute(string parameters)方法。
    /// </summary>
    public static class RunTextCommand
    {
        /// <summary>
        /// 执行用户输入的命令。执行成功，返回string.Empty。
        /// </summary>
        /// <param name="formatedUserInputedCommandText"></param>
        /// <returns>执行成功，返回string.Empty。</returns>
        public static string Run(string userInputedCommandText)
        {
            if (userInputedCommandText == null || userInputedCommandText.Length <= 0) return "　　命令文本不能为空。";

            string resultText = string.Empty;

            string formatedCommandText = FormatUserInputedCommandText(userInputedCommandText);

            string innerCommandText = ConvertToInnerCommandText(formatedCommandText);
            string parameters = GetCommandParametersText(formatedCommandText);

            resultText = RunCommand(innerCommandText, parameters);

            return resultText;
        }

        /// <summary>
        /// 命令文本（含“命令别名”，“命令参数”两部分，别名中不含空格，第一个空格后是参数字串，参数之间也以空格分隔。）
        /// 一律转换成小写，且“_”、“　”（全角空格）、“/”均会被转换为半角空格。
        /// 
        /// 根据用户输入的命令文本，查找命令映射表，返回内部命令文本。
        /// </summary>
        /// <param name="formatedUserInputedCommandText">（格式化后的）用户输入的命令文本</param>
        private static string ConvertToInnerCommandText(string formatedUserInputedCommandText)
        {
            if (formatedUserInputedCommandText == null || formatedUserInputedCommandText.Length <= 0) return null;

            int indexOfSpace = formatedUserInputedCommandText.IndexOf(" ");
            if (indexOfSpace < 0)
            {
                return formatedUserInputedCommandText;
            }
            else
            {
                return formatedUserInputedCommandText.Substring(0, indexOfSpace);
            }

            //先取出找到的第一个空格前面的字符串（这就是用户定义的“命令别名”），再读取命令映射表，找类名！！！
        }

        /// <summary>
        /// 格式化用户输入的命令文本。
        /// 
        /// 将“　”（全角空格）、“_”、“/”都转换成半角空格；所有字母都转换成小写。
        /// 
        /// 
        /// </summary>
        /// <param name="formatedUserInputedCommandText"></param>
        public static string FormatUserInputedCommandText(string userInputedCommandText)
        {
            //格式化命令。
            string text = userInputedCommandText.ToLower();
            text = text.Replace("　", " ");
            text = text.Replace("_", " ");
            text = text.Replace("/", " ");

            //暂时不对破折号进行转换，因为会造成需要破折号的时候无法使用。
            //text = text.Replace("—", " ");//极点五笔破折号
            //text = text.Replace("—", " ");//微软拼音破折号
            //text = text.Replace("—", " ");//微软拼音ABC破折号
            //text = text.Replace("—", " ");//简体中文全拼破折号
            //——上面这几种输入法使用的破折号均为字符：8212|8212|8212|8212

            text = text.TrimStart(' ');

            //全角数字、全角字母的半角化。
            text = text.Replace("？", "?");
            text = text.Replace("！", "!");
            //TODO: 将来可能还会遇到一些需要转换的全角字符。

            text = text.Replace("Ａ", "a");
            text = text.Replace("Ｂ", "b");
            text = text.Replace("Ｃ", "c");
            text = text.Replace("Ｄ", "d");
            text = text.Replace("Ｅ", "e");
            text = text.Replace("Ｆ", "f");
            text = text.Replace("Ｇ", "g");
            text = text.Replace("Ｈ", "h");
            text = text.Replace("Ｉ", "i");
            text = text.Replace("Ｊ", "j");
            text = text.Replace("Ｋ", "k");
            text = text.Replace("Ｌ", "l");
            text = text.Replace("Ｍ", "m");
            text = text.Replace("Ｎ", "n");
            text = text.Replace("Ｏ", "o");
            text = text.Replace("Ｐ", "p");
            text = text.Replace("Ｑ", "q");
            text = text.Replace("Ｒ", "r");
            text = text.Replace("Ｓ", "s");
            text = text.Replace("Ｔ", "t");
            text = text.Replace("Ｕ", "u");
            text = text.Replace("Ｖ", "v");
            text = text.Replace("Ｗ", "w");
            text = text.Replace("Ｘ", "x");
            text = text.Replace("Ｙ", "y");
            text = text.Replace("Ｚ", "z");

            text = text.Replace("ａ", "a");
            text = text.Replace("ｂ", "b");
            text = text.Replace("ｃ", "c");
            text = text.Replace("ｄ", "d");
            text = text.Replace("ｅ", "e");
            text = text.Replace("ｆ", "f");
            text = text.Replace("ｇ", "g");
            text = text.Replace("ｈ", "h");
            text = text.Replace("ｉ", "i");
            text = text.Replace("ｊ", "j");
            text = text.Replace("ｋ", "k");
            text = text.Replace("ｌ", "l");
            text = text.Replace("ｍ", "m");
            text = text.Replace("ｎ", "n");
            text = text.Replace("ｏ", "o");
            text = text.Replace("ｐ", "p");
            text = text.Replace("ｑ", "q");
            text = text.Replace("ｒ", "r");
            text = text.Replace("ｓ", "s");
            text = text.Replace("ｔ", "t");
            text = text.Replace("ｕ", "u");
            text = text.Replace("ｖ", "v");
            text = text.Replace("ｗ", "w");
            text = text.Replace("ｘ", "x");
            text = text.Replace("ｙ", "y");
            text = text.Replace("ｚ", "z");


            text = text.Replace("１", "1");
            text = text.Replace("２", "2");
            text = text.Replace("３", "3");
            text = text.Replace("４", "4");
            text = text.Replace("５", "5");
            text = text.Replace("６", "6");
            text = text.Replace("７", "7");
            text = text.Replace("８", "8");
            text = text.Replace("９", "9");
            text = text.Replace("０", "0");
            return text;
        }

        /// <summary>
        /// 取用户输入的命令文本中的参数部分。
        /// 
        /// </summary>
        /// <param name="formatedUserInputedCommandText">应传入（格式化后的）用户输入的命令文本。</param>
        private static string GetCommandParametersText(string formatedUserInputedCommandText)
        {
            if (formatedUserInputedCommandText == null || formatedUserInputedCommandText.Length <= 0) return string.Empty;

            int indexOfSpace = formatedUserInputedCommandText.IndexOf(" ");
            if (indexOfSpace < 0) return string.Empty;

            return formatedUserInputedCommandText.Substring(indexOfSpace + 1);
        }

        /// <summary>
        /// 找出本模块中所有类名以“_TC”开头的类，并且将类名与传入的“innerCommandText”进行对比，
        /// 如果找到相同的，则尝试调用此类提供的：
        /// static string Execute(string parameters)方法。
        /// 
        /// 根据提供的内部命令列表，找到对应的命令类，执行此类的Execute(string parameters)方法。
        /// 执行成功，返回string.Empty。
        /// </summary>
        /// <param name="innerCommandText">内部命令文本。</param>
        /// <param name="parameters">以半角空格分隔的字符串参数列表，可以为null。</param>
        /// <returns>执行成功，返回string.Empty。</returns>
        private static string RunCommand(string innerCommandText, string parameters)
        {
            //自定义的文本命令类，必须以_TC开头。
            if (innerCommandText == null || innerCommandText.Length <= 0)
            {
                return "　　未找到内置命令：" + innerCommandText;
                //所有命令类都是以“_TC”开头，因此转换后本来至少应是4，但是因打算支持中文命令，因此可能较短，但再少不能为空。
            }

            Type[] _tcClasses = Globals.MainWindow.GetType().Module.FindTypes(Module.FilterTypeNameIgnoreCase, "_tc*");

            //#region 复制所有字符串命令类的名称，每行一个。
            //StringBuilder sb = new StringBuilder();

            //foreach (Type t in _tcClasses)
            //{
            //    sb.Append(t.Name + "\r\n");
            //}

            //System.Windows.Clipboard.SetText(sb.ToString()); 
            //#endregion

            //StringBuilder sb = new StringBuilder();

            //foreach (Type t in _tcClasses)
            //{
            //    sb.Append(t.Name.ToLower());
            //}

            //System.Windows.Forms.Clipboard.SetText(sb.ToString());

            foreach (Type t in _tcClasses)
            {
                if (t.Name.ToLower() == innerCommandText)
                {
                    MethodInfo methodInfo = t.GetMethod("Execute", new Type[] { typeof(string) });
                    if (methodInfo == null) continue;

                    Object result = methodInfo.Invoke(null, new object[] { parameters });
                    return result as string;
                }
                else
                {
                    TextCommandAttribute tna = (TextCommandAttribute)
                        Attribute.GetCustomAttribute(t, typeof(TextCommandAttribute));

                    //这是为防止tna.AliasNames.Contains(cmdText)方法在比较（zh和mrzh）时出错。
                    string cmdText = innerCommandText;
                    if (innerCommandText.StartsWith("/") == false)
                    {
                        cmdText = "/" + innerCommandText;
                    }

                    if (innerCommandText.EndsWith("/") == false)
                    {
                        cmdText += "/";
                    }

                    if (tna != null && tna.AliasNames.Contains(cmdText))
                    {
                        MethodInfo methodInfo = t.GetMethod("Execute", new Type[] { typeof(string) });
                        if (methodInfo == null) continue;

                        Object result = methodInfo.Invoke(null, new object[] { parameters });
                        return result as string;
                    }
                }
            }

            return "　　未找到内置命令：" + innerCommandText;
        }
    }
}
